package com.top.web.hooker.common;

import android.app.Activity;
import android.content.Context;
import android.view.View;

import com.top.web.hooker.common.ViewManager.IFindViewByID;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.HashMap;
import java.util.Map;

public class ViewFinder
{
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.FIELD)
    public @interface ViewTag
    {
        int ID() default -1;

        String Name() default "";
    }

    public <T> void find(final View view, T tag)
    {
        find(new IFindViewByID()
        {
            @Override
            public Context getContext()
            {
                return view.getContext();
            }

            @Override
            public View findViewById(int id)
            {
                return view.findViewById(id);
            }
        }, tag);
    }

    public <T> void find(final Activity activity, T tag)
    {
        find(new IFindViewByID()
        {

            @Override
            public Context getContext()
            {
                return activity;
            }

            @Override
            public View findViewById(int id)
            {
                return activity.findViewById(id);
            }
        }, tag);
    }

    @SuppressWarnings("unchecked")
    public <T> T find(final IFindViewByID finder, Class<?>[] interCls)
    {
        return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(), interCls, new InvocationHandler()
        {
            Map<Method, View> _viewMap = new HashMap<Method, View>();

            @Override
            public Object invoke(Object arg0, Method method, Object[] arg2) throws Throwable
            {
                if (_viewMap.containsKey(method))
                    return _viewMap.get(method);

                ViewTag vTag = method.getAnnotation(ViewTag.class);
                if (vTag != null)
                {
                    int id = -1;

                    if (vTag.ID() != -1)
                    {
                        id = vTag.ID();
                    }
                    else if (vTag.Name() != null && vTag.Name() != "")
                    {
                        id = findIDByName(finder.getContext(), vTag.Name());
                    }

                    _viewMap.put(method, finder.findViewById(id));
                }
                else _viewMap.put(method, null);

                return _viewMap.get(method);
            }
        });

    }

    public <T> void find(IFindViewByID finder, T tag)
    {
        Class<?> cls = tag.getClass();

        for (Field item : cls.getDeclaredFields())
        {
            ViewTag vTag = item.getAnnotation(ViewTag.class);
            if (vTag != null)
            {
                int id = -1;

                if (vTag.ID() != -1)
                {
                    id = vTag.ID();
                }
                else if (vTag.Name() != null && vTag.Name() != "")
                {
                    id = findIDByName(finder.getContext(), vTag.Name());
                }
                else continue;

                try
                {
                    item.setAccessible(true);
                    item.set(tag, finder.findViewById(id));
                }
                catch (IllegalArgumentException e)
                {
                    e.printStackTrace();
                }
                catch (IllegalAccessException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }

    int findIDByName(Context context, String name)
    {
        return context.getResources().getIdentifier(name, "id/", context.getPackageName());
    }
}
